/*
 * @Title Gson.java
 * @Copyright Copyright(c) 2018
 * @Company com.lizhen
 * @author lizhen
 * @version 0.0.1
 */
package com.lizhen.core.function.gson;

import com.google.gson.*;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.lizhen.core.function.gson.entity.Person;

import java.io.*;
import java.util.Arrays;

/**
 * @author lizhen
 */
public class GsonDemo {
    static String JSON_FILE_PATH = "1.8\\api\\main\\resource\\com\\lizhen\\core\\function\\gson\\GsonDemo\\GsonDemo.json";

    /**
     * @author lizhen
     */
    public GsonDemo() {
    }

    private static void handleJsonArray(JsonReader reader) throws IOException {
        reader.beginArray();
        while (true) {
            JsonToken token = reader.peek();
            if (token.equals(JsonToken.END_ARRAY)) {
                reader.endArray();
                break;
            } else if (token.equals(JsonToken.BEGIN_OBJECT)) {
                handleJsonObject(reader);
            } else if (token.equals(JsonToken.END_OBJECT)) {
                reader.endObject();
            } else {
                System.out.print(reader.nextInt() + " ");
            }
        }
    }

    private static void handleJsonObject(JsonReader reader) throws IOException {
        String fieldname = null;
        reader.beginObject();
        while (reader.hasNext()) {
            JsonToken token = reader.peek();
            if (token.equals(JsonToken.BEGIN_ARRAY)) {
                System.out.print("Marks: [ ");

                handleJsonArray(reader);

                System.out.println("]");
            } else if (token.equals(JsonToken.END_OBJECT)) {
                reader.endObject();
                return;
            } else {
                if (token.equals(JsonToken.NAME)) {
                    // get the current token
                    fieldname = reader.nextName();
                }
                if ("name".equals(fieldname)) {
                    // move to next token
                    token = reader.peek();

                    System.out.println("Name: " + reader.nextString());
                }
                if ("age".equals(fieldname)) {
                    // move to next token
                    token = reader.peek();

                    System.out.println("Age:" + reader.nextInt());
                }
                if ("verified".equals(fieldname)) {
                    // move to next token
                    token = reader.peek();

                    System.out.println("Verified:" + reader.nextBoolean());
                }
            }
        }
    }

    private static void writeJSON(Person person) throws IOException {
        GsonBuilder builder = new GsonBuilder();
        Gson gson = builder.create();
        FileWriter writer = new FileWriter(JSON_FILE_PATH);
        writer.write(gson.toJson(person));
        writer.close();
    }

    private static Person readJSON() throws FileNotFoundException {
        GsonBuilder builder = new GsonBuilder();
        Gson gson = builder.create();
        BufferedReader bufferedReader = new BufferedReader(new FileReader(JSON_FILE_PATH));
        Person person = gson.fromJson(bufferedReader, Person.class);
        return person;
    }

    /**
     * @author lizhen
     */
    public static void main(String[] args) throws IOException {
        GsonDemo gsonDemo = new GsonDemo();
        gsonDemo.jsonVersion();
        gsonDemo.jsonSerializeNulls();
        gsonDemo.jsonStream();
        gsonDemo.jsonTree();
        gsonDemo.jsonObject();
        gsonDemo.jsonBasic();
        gsonDemo.jsonVariable();
        gsonDemo.jsonFile();
    }

    /**
     * @author lizhen
     */
    private void jsonVersion() {
        String jsonString = "{\"name\":\"小明\", \"age\":100}";
        GsonBuilder builder = new GsonBuilder();
        builder.setVersion(1.0);
        builder.setPrettyPrinting();
        Gson gson = builder.create();
        Person person = gson.fromJson(jsonString, Person.class);
        jsonString = gson.toJson(person);

        System.out.println(person);
        System.out.println(jsonString);
    }

    /**
     * @author lizhen
     */
    private void jsonSerializeNulls() {
        String jsonString = "{\"name\":\"小明\"}";
        GsonBuilder builder = new GsonBuilder();
        builder.serializeNulls();
        builder.setPrettyPrinting();
        Gson gson = builder.create();
        Person person = gson.fromJson(jsonString, Person.class);
        jsonString = gson.toJson(person);

        System.out.println(person);
        System.out.println(jsonString);
    }

    /**
     * @author lizhen
     */
    private void jsonStream() throws IOException {
        String jsonString = "{\"name\":\"小明\", \"age\":18,\"verified\":false,\"marks\": [100,90,85]}";
        JsonReader jsonReader = new JsonReader(new StringReader(jsonString));
        handleJsonObject(jsonReader);
    }

    /**
     * @author lizhen
     */
    private void jsonTree() {
        String jsonString = "{\"name\":\"小明\", \"age\":26,\"verified\":false,\"marks\": [100,90,85]}";
        JsonParser parser = new JsonParser();
        JsonElement rootNode = parser.parse(jsonString);
        if (rootNode.isJsonObject()) {
            JsonObject details = rootNode.getAsJsonObject();
            JsonElement nameNode = details.get("name");
            JsonElement ageNode = details.get("age");
            JsonElement verifiedNode = details.get("verified");

            System.out.println("Age: " + ageNode.getAsInt());
            System.out.println("Name: " + nameNode.getAsString());
            System.out.println("Verified: " + (verifiedNode.getAsBoolean() ? "Yes" : "No"));

            JsonArray marks = details.getAsJsonArray("marks");

            for (int i = 0; i < marks.size(); i++) {
                JsonPrimitive value = marks.get(i).getAsJsonPrimitive();
                if (i == 0) {
                    System.out.printf("Marks: [ %s ", value.getAsInt());
                } else if (i == marks.size() - 1) {
                    System.out.printf("%s ]%n", value.getAsInt());
                } else {
                    System.out.printf("%s ", value.getAsInt());
                }
            }
        }
    }

    /**
     * @author lizhen
     */
    private void jsonObject() {
        Gson gson = new Gson();
        Person person = new Person();
        person.setAge(18);
        person.setName("小明");
        String jsonString = gson.toJson(person);
        Person person1 = gson.fromJson(jsonString, Person.class);

        System.out.println(jsonString);
        System.out.println(person1);
    }

    /**
     * @author lizhen
     */
    private void jsonBasic() {
        String name = "小明";
        long rollNo = 1;
        boolean verified = false;
        int[] marks = {100, 90, 85};
        Gson gson = new Gson();

        // Serialization
        System.out.println("{");
        System.out.println("name: " + gson.toJson(name) + ",");
        System.out.println("rollNo: " + gson.toJson(rollNo) + ",");
        System.out.println("verified: " + gson.toJson(verified) + ",");
        System.out.println("marks:" + gson.toJson(marks));
        System.out.println("}");

        // De-serialization
        name = gson.fromJson(name, String.class);
        rollNo = gson.fromJson(String.valueOf(rollNo), Long.class);
        verified = gson.fromJson(String.valueOf(verified), Boolean.class);
        marks = gson.fromJson(Arrays.toString(marks), int[].class);

        System.out.println("name: " + name);
        System.out.println("rollNo: " + rollNo);
        System.out.println("verified: " + verified);
        System.out.println("marks:" + Arrays.toString(marks));
    }

    private void jsonVariable() {
        String jsonString = "{\"name\":\"小明\", \"age\":100}";
        GsonBuilder builder = new GsonBuilder();
        builder.setPrettyPrinting();
        Gson gson = builder.create();
        Person person = gson.fromJson(jsonString, Person.class);
        jsonString = gson.toJson(person);

        System.out.println(person);
        System.out.println(jsonString);
    }

    private void jsonFile() throws IOException {
        GsonDemo gson = new GsonDemo();
        Person person = new Person();
        person.setName("小明");
        person.setAge(10);
        writeJSON(person);
        Person person2 = gson.readJSON();

        System.out.println(person);
        System.out.println(person2);
    }
}
